package edu.hawaii.myisern.action;

import java.io.File;
import edu.hawaii.myisern.model.MyIsernModel;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.ValidationErrors;

/**
 * Provides a web interface for import and export.
 * 
 * @author Ed Kim
 * @author Jon Lao
 * @author JianFei Liao
 * @author Jared Sunouchi
 */
public class ImportExportActionBean implements ActionBean {

  /** Required by the ActionBean interface. */
  private ActionBeanContext context;
  /** An singleton instance of the MyIsernModel. */
  private MyIsernModel myModel = MyIsernModel.getInstance();
  /** A string for "/import.jsp". */
  private static final String IMPORT_JSP_PAGE = "/import.jsp";
  /** A message to display information. */
  private String message = "";
  /** The FileBean for researchers XML file. */
  private FileBean researchersFile;
  /** The FileBean for organizations XML file. */
  private FileBean organizationsFile;
  /** The FileBean for collaborations XML file. */
  private FileBean collaborationsFile;
  /** Whether the files were exported or not */
  private boolean exported = false;
  private String exportMessage = "";

  /**
   * Returns the context. Required by the interface.
   * 
   * @return the ActionBeanContext.
   */
  public ActionBeanContext getContext() {
    return context;
  }

  /**
   * Sets the context. Required by the interface.
   * 
   * @param context The ActionBeanContext to set.
   */
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }
  
//  /**
//   * Gets the FileBean for researchers XML file.
//   * 
//   * @return The FileBean for researchers XML file.
//   */
//  public FileBean getResearchersFile() {
//    return this.researchersFile;
//  }

  /**
   * Sets the FileBean for researchers XML file.
   * 
   * @param researchersFile The FileBean to set.
   */
  public void setResearchersFile(FileBean researchersFile) {
    this.researchersFile = researchersFile;
  }
  
//  /**
//   * Gets the FileBean for organizations XML file.
//   * 
//   * @return The FileBean for organizations XML file.
//   */
//  public FileBean getOrganizationsFile() {
//    return this.organizationsFile;
//  }
  
  /**
   * Sets the FileBean for organizations XML file.
   * 
   * @param organizationsFile The FileBean to set.
   */
  public void setOrganizationsFile(FileBean organizationsFile) {
    this.organizationsFile = organizationsFile;
  }
  
//  /**
//   * Gets the FileBean for collaborations XML file.
//   * 
//   * @return The FileBean for collaborations XML file.
//   */
//  public FileBean getCollaborationsFile() {
//    return this.collaborationsFile;
//  }
  
  /**
   * Sets the FileBean for collaborations XML file.
   * 
   * @param collaborationsFile The FileBean to set.
   */
  public void setCollaborationsFile(FileBean collaborationsFile) {
    this.collaborationsFile = collaborationsFile;
  }
  
  /**
   * Gets the message string.
   * 
   * @return The message string.
   */
  public String getMessage() {
    return this.message;
  }
  
//  /**
//   * Sets the message string.
//   * 
//   * @param message The message string to set.
//   */
//  public void setMessage(String message) {
//    this.message = message;
//  }
  
  /**
   * Gets whether the files were exported or not.
   * 
   * @return Whether the files were exported or not.
   */
  public boolean getExported() {
    return this.exported;
  }
  
  /**
   * Gets the export message.
   * 
   * @return The export message.
   */
  public String getExportMessage() {
    return this.exportMessage;
  }
  
  /**
   * Imports the researchers XML data.
   * 
   * @return A new resolution
   */
  public boolean importResearchersData() {
    boolean isImported = true;
    
    try {
      if (this.researchersFile != null) {
        // create a temporary researchers file for importing
        String researchersFilePath = System.getProperty("user.dir") + "/researchers.temp.xml";
        File tempResearchersFile = new File(researchersFilePath);
        // copy the data from the FileBean to the temporary file
        this.researchersFile.save(tempResearchersFile);
        // import data from the temporary file
        if (this.myModel.importResearchersXml(researchersFilePath)) {
          this.message = "The researchers data is successfully imported.";
        }
        else {
          isImported = false;
        }
        if (tempResearchersFile.delete()) {
          System.out.println("Deleted " + researchersFilePath);
        }
      }
    }
    catch (Exception e) {
      isImported = false;
      e.printStackTrace();
    }
    return isImported;
  }
  
  /**
   * Imports the organizations XML data.
   * 
   * @return A new resolution
   */
  public boolean importOrganizationsData() {
    boolean isImported = true;
    
    try {
      if (this.organizationsFile != null) {
        // create a temporary organizations file for importing
        String organizationsFilePath = System.getProperty("user.dir") + "/organizations.temp.xml";
        File tempOrganizationsFile = new File(organizationsFilePath);
        // copy the data from the FileBean to the temporary file
        this.organizationsFile.save(tempOrganizationsFile);
        // import data from the temporary file
        if (this.myModel.importOrganizationsXml(organizationsFilePath)) {
          this.message = "The organizations data is successfully imported.";
        }
        else {
          isImported = false;
        }
        if (tempOrganizationsFile.delete()) {
          System.out.println("Deleted " + organizationsFilePath);
        }
      }
    }
    catch (Exception e) {
      isImported = false;
      e.printStackTrace();
    }
    return isImported;
  }
  
  /**
   * Imports the collaborations XML data.
   * 
   * @return A new resolution
   */
  public boolean importCollaborationsData() {
    boolean isImported = true;
    
    try {
      if (this.collaborationsFile != null) {
        // create a temporary collaborations file for importing
        String collaborationsFilePath = System.getProperty("user.dir") + 
            "/collaborations.temp.xml";
        File tempCollaborationsFile = new File(collaborationsFilePath);
        // copy the data from the FileBean to the temporary file
        this.collaborationsFile.save(tempCollaborationsFile);
        // import data from the temporary file
        if (this.myModel.importCollaborationsXml(collaborationsFilePath)) {
          this.message = "The collaborations data is succesfully imported.";
        }
        else {      
          isImported = false;
        }
        if (tempCollaborationsFile.delete()) {
          System.out.println("Deleted " + collaborationsFilePath);
        }
      }
    }
    catch (Exception e) {
      isImported = false;
      e.printStackTrace();
    }
    return isImported;
  }
  
  /**
   * The handler for importing researchers data.
   * 
   * @return A new resolution. 
   */
  public Resolution importResearchersDataHandler() {
    ValidationErrors errors = new ValidationErrors();
    // if the file is not provided
    if (this.researchersFile == null) {
      errors.add("noResearchersData", new SimpleError("The researchers data file is required."));
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    // else, check if the import is successful
    else {
      boolean isImported = this.importResearchersData();
      if (!isImported) {
        errors.add("invalidResearchersData", new SimpleError("The researchers data is invalid."));
        this.getContext().setValidationErrors(errors);
        return this.getContext().getSourcePageResolution();
      }
    }
    return new RedirectResolution(IMPORT_JSP_PAGE).flash(this);
  }
  
  /**
   * The handler for importing organizations data.
   * 
   * @return A new resolution. 
   */
  public Resolution importOrganizationsDataHandler() {
    ValidationErrors errors = new ValidationErrors();
    // if the file is not provided
    if (this.organizationsFile == null) {      
      errors.add("noOrganizationsData", 
          new SimpleError("The organizations data file is required."));
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    // else, check if the import is successful
    else {
      boolean isImported = this.importOrganizationsData();
      if (!isImported) {
        errors.add("invalidOrganizationsData", 
            new SimpleError("The organizations data is invalid."));
        this.getContext().setValidationErrors(errors);
        return this.getContext().getSourcePageResolution();
      }
    }
    return new RedirectResolution(IMPORT_JSP_PAGE).flash(this);
  }
  
  /**
   * The handler for importing collaborations data.
   * 
   * @return A new resolution. 
   */
  public Resolution importCollaborationsDataHandler() {
    ValidationErrors errors = new ValidationErrors();
    // if the file is not provided
    if (this.collaborationsFile == null) {
      errors.add("noCollaborationsData", 
          new SimpleError("The collaborations data file is required."));
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    // else, check if the import is successful
    else {
      boolean isImported = this.importCollaborationsData();
      if (!isImported) {
        errors.add("invalidCollaborationsData", 
            new SimpleError("The collaborations data is invalid."));
        this.getContext().setValidationErrors(errors);
        return this.getContext().getSourcePageResolution();
      }
    }
    return new RedirectResolution(IMPORT_JSP_PAGE).flash(this);
  }
  
  /**
   * The handler for importing all data.
   * 
   * @return A new resolution.
   */
  @DefaultHandler
  public Resolution importAllData() {
    ValidationErrors errors = new ValidationErrors();
    // ensure all files are provided
    if (this.researchersFile == null || 
        this.organizationsFile == null || 
        this.collaborationsFile == null) {
      errors.add("missingFields", new SimpleError("All data files are required."));
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    // only succeed when all the import are successful
    if (this.importResearchersData() &&
        this.importOrganizationsData() &&
        this.importCollaborationsData()) {
      this.message = "All data are successfully imported.";
    }
    // determine which import has failed
    else {
      if (!this.importResearchersData()) {
        errors.add("researchersError", new SimpleError("Researchers data is invalid."));
      }
      if (!this.importOrganizationsData()) {
        errors.add("organizationsError", new SimpleError("Organizations data is invalid."));
      }
      if (!this.importCollaborationsData()) {
        errors.add("collaborationsError", new SimpleError("Collaborations data is invalid."));
      }
      // reset the message for the successful import, if any 
      this.message = "";
      this.getContext().setValidationErrors(errors);
      return this.getContext().getSourcePageResolution();
    }
    return new RedirectResolution(IMPORT_JSP_PAGE).flash(this);
  }

  /**
   * Exports the data to XML files.
   * 
   * @return A new resolution.
   */
  public Resolution export() {
    // specify the location for the export files
    String researchersFile = System.getProperty("user.home") + 
        "/.myisern/researchers.export.xml";
    String organizationsFile = System.getProperty("user.home") + 
        "/.myisern/organizations.export.xml";
    String collaborationsFile = System.getProperty("user.home") + 
        "/.myisern/collaborations.export.xml";
    // display different message for different export results
    if (this.myModel.exportXml(researchersFile, organizationsFile, collaborationsFile)) {
      this.exportMessage = "Export succeeded!\n" + 
        "\nResearchers data is exported to " + "\n\t" + researchersFile +
        "\nOrganizations data is exported to " + "\n\t" + organizationsFile +
        "\nCollaborations data is exported to " + "\n\t" + collaborationsFile;
      this.exportMessage = this.exportMessage.replace('/', '\\');
      this.exported = true;
    }
    else {
      this.exportMessage = "Export failed!";
      this.exported = true;
    }
    return new RedirectResolution("/home.jsp").flash(this);
  }
}